﻿using Newtonsoft.Json;
using System;
using System.Configuration;
using System.Drawing;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using dc_power_monitor.userControl;
using Modbus.Device;

namespace dc_power_monitor.forms
{
    public partial class homeForm : Form
    {
        home_uc home_Uc;
        user_uc user_Uc;
        log_uc log_Uc;
        setting_uc setting_Uc;


        private static IModbusMaster master;

        public delegate void sendData(RootObject pp);
        sendData send;

        public delegate void sendData1(inputParam pp);
        sendData1 send_set;

        public delegate void sendData2(modParam pp);
        sendData2 send_set_mod;

        user nowUser = new user();
        int serialConFlag = 0;

        private recordHelper rec;

        public ushort coil_start_stop = 0x0001;
        public ushort coil_ctr_mod = 0x0002;
        public ushort coil_vol_mod = 0x0004;

        public ushort reg_fault_mod_1 = 0x000a;
        public ushort reg_fault_mod_2 = 0x000b;
        public ushort reg_fault_mod_3 = 0x000c;
        public ushort reg_fault_mod_4 = 0x000d;
        public ushort reg_online_mod_1 = 0x000e;
        public ushort reg_online_mod_2 = 0x000f;
        public ushort reg_online_mod_3 = 0x0011;
        public ushort reg_online_mod_4 = 0x0012;

        public ushort hold_v_set = 0x0011;
        public ushort hold_i_set = 0x0012;

        public ushort input_v_out = 0x0021;
        public ushort input_i_out = 0x0022;
        public ushort input_p_out = 0x0023;

        public ushort input_i = 0x0024;
        public ushort input_uv = 0x0025;
        public ushort input_vw = 0x0026;
        public ushort input_wu = 0x0027;
        public ushort input_hz = 0x0028;

        public ushort input_mod1_i = 0x0029;
        public ushort input_mod2_i = 0x002a;
        public ushort input_mod3_i = 0x002b;
        public ushort input_mod4_i = 0x002c;





        public homeForm(user users)
        {
            InitializeComponent();
            timerDate.Start();
            
            rec = new recordHelper("log_opreat_fault.db");

            log_Uc = new log_uc(users.level);
            user_Uc = new user_uc();
            home_Uc = new home_uc();
            setting_Uc = new setting_uc();

            nowUser = users;
            send += home_Uc.RecieveData;
            send_set += setting_Uc.RecieveData;
            send_set_mod += setting_Uc.RecieveData_mod;

            home_Uc.sendHold += this.otherFormModbusHoldWrite;
            home_Uc.sendCoil += this.otherFormModbusCoilWrite;

            setting_Uc.sendSerial_set += this.otherFormModbusCoilWrite;

            addControlToPanle(home_Uc);
            labNowUser.Text = users.username.ToString();

            labNowLevel.Text = users.level.ToString();

            serialReConnect();

            master = ModbusSerialMaster.CreateRtu(serialPort1);
            master.Transport.ReadTimeout = 100;
            master.Transport.Retries = 0;//重试次数

            timer1.Start();
            timer2.Start();
        }
        public void otherFormModbusCoilWrite(ushort add, bool value)
        {
            try
            {
                master.WriteSingleCoil(0x01, add, value);
            }
            catch
            {
                MessageBox.Show("打开串口失败！请检查COM口设置");
            }
        }

        public void otherFormModbusHoldWrite(ushort add, ushort value)
        {
            try
            {
                master.WriteSingleRegister(0x01, add, value);
            }
            catch
            {
                MessageBox.Show("打开串口失败！请检查COM口设置");
            }
        }
        public void otherFormSerialSend(string str)
        {
            try
            {
                serialPort1.Write(str);
                master.WriteSingleCoil(0x01, 0x01, true);
            }
            catch
            {
                MessageBox.Show("打开串口失败！请检查COM口设置");
            }
            
        }

        private void serialReConnect()
        {
            try
            {
                serialPort1.Close();

                serialPort1.PortName = ConfigurationManager.AppSettings["COM"];                   //将串口设备的串口号属性设置为  comboBox1复选框中选择的串口号
                serialPort1.BaudRate = 9600;  //将串口设备的波特率属性设置为  comboBox2复选框中选择的波特率
                serialPort1.Open();
            }
            catch
            {
                //MessageBox.Show("打开串口失败！，请重新设置");
            }
        }

        private delegate void SetTextCallBack(string text);
        private void SetText(SetTextCallBack func, string text)
        {
            if (this.labConnectSta.InvokeRequired)
            {

                this.Invoke(func, new object[] { text });
            }
            else
            {
                func(text);
            }
        }

        private void LoadData(string txt)
        {
            this.labConnectSta.Text = txt;
        }





        private void movePanSide(Control btn)
        {
            panSide.Top = btn.Top;
            panSide.Height = btn.Height;
        }

        private void homeForm_Load(object sender, EventArgs e)
        {



        }

        private void addControlToPanle(Control c)
        {
            c.Dock = DockStyle.Fill;
            panelControl.Controls.Clear();
            panelControl.Controls.Add(c);
        }

        private void btnHome_Click(object sender, EventArgs e)
        {
            movePanSide(btnHome);


            addControlToPanle(home_Uc);
        }

        private void btnSet_Click(object sender, EventArgs e)
        {
            movePanSide(btnSet);
            addControlToPanle(setting_Uc);
        }

        private void btnLog_Click(object sender, EventArgs e)
        {
            movePanSide(btnLog);

            addControlToPanle(log_Uc);

            log_Uc.update_log();
        }

        private void btnUser_Click(object sender, EventArgs e)
        {

            if (nowUser.level != authority.管理员)
            {
                MessageBox.Show("权限不够，需要管理员权限");
                return;
            }
            movePanSide(btnUser);

            addControlToPanle(user_Uc);
        }

        private void label3_Click(object sender, EventArgs e)
        {

        }



        private void button5_Click(object sender, EventArgs e)
        {
            rec.addOpreatRecord(nowUser.username, "关闭监控后台");
            this.Dispose();
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            DateTime date = DateTime.Now;
            labelTime.Text = date.ToString("yyyy-MM-dd hh:mm:ss");


        }

        private void labelTime_Click(object sender, EventArgs e)
        {

        }

        private void btnMax_Click(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Maximized)
            {
                this.WindowState = FormWindowState.Normal;
            }
            else
            {
                this.FormBorderStyle = FormBorderStyle.None;
                this.MaximumSize = new Size(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
                this.WindowState = FormWindowState.Maximized;
            }
        }

        private void btnMin_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Minimized;
        }

        private void panelControl_Paint(object sender, PaintEventArgs e)
        {

        }
        [DllImport("user32.dll")]
        public static extern bool ReleaseCapture();

        [DllImport("user32.dll")]
        public static extern bool SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);

        private const int VM_NCLBUTTONDOWN = 0XA1;//定义鼠标左键按下
        private const int HTCAPTION = 2;
        private void homeForm_Click(object sender, EventArgs e)
        {





        }

        private void panel2_MouseDown(object sender, MouseEventArgs e)
        {
            ReleaseCapture();
            //发送消息 让系统误以为在标题栏上按下鼠标
            SendMessage((IntPtr)this.Handle, VM_NCLBUTTONDOWN, HTCAPTION, 0);
        }

        private bool serialRecviceHeartCheck(string rec)
        {
            if (string.Compare(rec, "heart") == 0)
            {
                serialConFlag++;
                return true;
            }

            return false;
        }

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {


            try
            {
                //Thread.Sleep(300);
                //string str = serialPort1.ReadExisting();   //读取串口接收缓冲区字符串

                ////serialRecviceHeartCheck(str);

                //Console.WriteLine(str);

                //RootObject pp = JsonConvert.DeserializeObject<RootObject>(str); ;
                //serialConFlag++;

                //send.BeginInvoke(pp, null, null);
                //send_set.BeginInvoke(pp, null, null);
            }
            catch (Exception)
            {


            }

        }


        private void btnLogout_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
            timer1.Stop();
            timer2.Stop();

            rec.addOpreatRecord(nowUser.username, "注销");

            formLogin anotherForm = new formLogin();                        //定义新窗体
            this.Hide();                                      //隐藏旧窗体
            anotherForm.ShowDialog();                         //展示新窗体


            Application.ExitThread();
            this.Close();
        }

        private void panel4_Paint(object sender, PaintEventArgs e)
        {

        }

        private void panSide_Paint(object sender, PaintEventArgs e)
        {

        }


        private ushort[] v_output;
        private ushort[] i_output;
        private ushort[] p_output;

        private ushort[] v_set_hold;
        private ushort[] i_set_hold;

        private ushort[] i_hold;
        private ushort[] hz_hold;
        private ushort[] uv_hold;
        private ushort[] vw_hold;
        private ushort[] wu_hold;

        private bool[] sta_coil;
        private bool[] ctr_mod_coil;
        private bool[] vol_mod_coil;

        private bool[] mod_online;

        private bool[] dev_sta;
        private bool[] mod_fault;
        private bool[] dis_sta;

        private ushort[] errcode;
        private ushort[] mod_i;

        private async void AcquireStatus()
        {
            try
            {
                v_output = await master.ReadInputRegistersAsync(0x01, input_v_out, 1);
                i_output = await master.ReadInputRegistersAsync(0x01, input_i_out, 1);
                p_output = await master.ReadInputRegistersAsync(0x01, input_p_out, 1);

                errcode = await master.ReadInputRegistersAsync(0x01, 0x2F, 3);

                v_set_hold = await master.ReadHoldingRegistersAsync(0x01, hold_v_set, 1);
                i_set_hold = await master.ReadHoldingRegistersAsync(0x01, hold_i_set, 1);

                sta_coil = await master.ReadCoilsAsync(0x01, coil_start_stop, 1);
                ctr_mod_coil = await master.ReadCoilsAsync(0x01, coil_ctr_mod, 1);
                vol_mod_coil = await master.ReadCoilsAsync(0x01, coil_vol_mod, 1);

                dev_sta = await master.ReadInputsAsync(0x01, 5, 4);
                mod_online = await master.ReadInputsAsync(0x01, reg_online_mod_1, 4);
                mod_fault = await master.ReadInputsAsync(0x01, reg_fault_mod_1, 4);
                mod_i = await master.ReadInputRegistersAsync(0x01, input_mod1_i, 4);

                dis_sta = await master.ReadInputsAsync(0x01, 0x12, 1);

            }
            catch
            { 
            
            }
            
        }

        RootObject pp = new RootObject();
        modParam ppp = new modParam();

        private int con_flag = 0;
        private void timer1_Tick_1(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                try
                {
                    AcquireStatus();
                    if(v_output != null)
                        pp.vol = v_output[0].ToString();
                    if (i_output != null)
                        pp.cur = i_output[0].ToString();
                    if (p_output != null)
                        pp.pow = (p_output[0]).ToString();
                    if (sta_coil != null)
                        pp.sta = sta_coil[0];
                    if (v_set_hold != null)
                        pp.vSet = v_set_hold[0].ToString();
                    if (i_set_hold != null)
                        pp.cSet = i_set_hold[0].ToString();
                    if (ctr_mod_coil != null)
                        pp.ctrmod = ctr_mod_coil[0];
                    if (vol_mod_coil != null)
                        pp.volmod = vol_mod_coil[0];

                    if (dev_sta != null)
                        pp.devsta = dev_sta;

                    if (dis_sta != null)
                        pp.dissta = dis_sta[0];


                    if (errcode != null)
                        pp.errcode = errcode;


                    if (mod_fault != null)
                        ppp.mod_fault = mod_fault;
                    if (mod_online != null)
                        ppp.mod_online = mod_online;
                    if (mod_i != null)
                        ppp.mod_out_i = mod_i;

                    if (v_output != null)
                        send.Invoke(pp);
                    if (mod_fault != null)
                        send_set_mod.Invoke(ppp);

                    sta_coil = master.ReadCoils(0x01, coil_start_stop, 1);
                    SetText(LoadData, "设备已连接！");
                    con_flag = 0;
                }
                catch
                {
                    con_flag++;
                    if(con_flag > 5)
                    {
                        serialReConnect();
                        SetText(LoadData, "设备未连接！请检查COM口");
                    }
                }
            }
            else
            {
                serialReConnect();
                SetText(LoadData, "设备未连接！请检查COM口");
            }
            
            
            
        }

        inputParam ps = new inputParam();
        private void timer2_Tick(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
            {
                try
                {
                    i_hold = master.ReadInputRegisters(0x01, input_i, 1);
                    hz_hold = master.ReadInputRegisters(0x01, input_hz, 1);
                    uv_hold = master.ReadInputRegisters(0x01, input_uv, 1);
                    vw_hold = master.ReadInputRegisters(0x01, input_vw, 1);
                    wu_hold = master.ReadInputRegisters(0x01, input_wu, 1);

                    ps.inCur = i_hold[0].ToString();
                    ps.inHz = hz_hold[0].ToString();
                    ps.inUV = uv_hold[0].ToString();
                    ps.inVW = vw_hold[0].ToString();
                    ps.inWU = wu_hold[0].ToString();

                    send_set.Invoke(ps);
                }
                catch
                {

                }
            }
            
            
        }

        private void labConnectSta_Click(object sender, EventArgs e)
        {

        }
    }
}





